package com.example.mydownloader.ui.login

import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.view.View
import android.view.inputmethod.EditorInfo
import android.widget.EditText
import android.widget.Toast
import androidx.annotation.StringRes
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.example.mydownloader.ui.main.MainActivity
import com.example.mydownloader.R
import com.example.mydownloader.databinding.ActivityLoginBinding
import com.example.mydownloader.mymodule.log.LogUtil
import com.example.mydownloader.mymodule.sharedpreferences.SPConst
import com.example.mydownloader.mymodule.sharedpreferences.SPUtil
import java.util.ArrayList


class LoginActivity : AppCompatActivity() {

    private lateinit var loginViewModel: LoginViewModel
    private lateinit var binding: ActivityLoginBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityLoginBinding.inflate(layoutInflater)
        setContentView(binding.root)

        val username = binding.username
        val password = binding.password
        val login = binding.login
        val loading = binding.loading
        val rememberCheckBox = binding.rememberLoginData

        loginViewModel = ViewModelProvider(
            this, LoginViewModelFactory()
        )
            .get(LoginViewModel::class.java)

        loginViewModel.loginFormState.observe(this@LoginActivity, Observer {
            val loginState = it ?: return@Observer

            // disable login button unless both username / password is valid
            login.isEnabled = loginState.isDataValid

            if (loginState.usernameError != null) {
                username.error = getString(loginState.usernameError)
            }
            if (loginState.passwordError != null) {
                password.error = getString(loginState.passwordError)
            }
        })

        loginViewModel.loginResult.observe(this@LoginActivity, Observer {
            val loginResult = it ?: return@Observer

            loading.visibility = View.GONE
            if (loginResult.error != null) {
                showLoginFailed(loginResult.error)
            }
            if (loginResult.success != null) {
                updateUiWithUser(loginResult.success)
            }
        })

        username.afterTextChanged {
            loginViewModel.loginDataChanged(
                username.text.toString(),
                password.text.toString()
            )
        }

        password.apply {
            afterTextChanged {
                loginViewModel.loginDataChanged(
                    username.text.toString(),
                    password.text.toString()
                )
            }

            setOnEditorActionListener { _, actionId, _ ->
                when (actionId) {
                    EditorInfo.IME_ACTION_DONE ->
                        loginViewModel.login(
                            username.text.toString(),
                            password.text.toString()
                        )
                }
                false
            }

            login.setOnClickListener {
                loading.visibility = View.VISIBLE
                loginViewModel.login(username.text.toString(), password.text.toString())
            }
        }

        rememberCheckBox.isChecked = SPUtil.getBoolean(SPConst.REMEMBER_LOGIN_DATA)
        rememberCheckBox.setOnCheckedChangeListener { _, isChecked ->
            SPUtil.setBoolean(
                SPConst.REMEMBER_LOGIN_DATA,
                isChecked
            )
        }

        // 自动填入账号密码
        val strings = SPUtil.getStrings(SPConst.USERNAME, SPConst.PASSWORD)
        username.setText(strings[SPConst.USERNAME])
        password.setText(strings[SPConst.PASSWORD])
    }

    private fun updateUiWithUser(model: LoggedInUserView) {
        val welcome = getString(R.string.welcome)
        val displayName = model.displayName
        Toast.makeText(
            applicationContext,
            "$welcome $displayName",
            Toast.LENGTH_LONG
        ).show()
        // 跳转到主界面
        val user = loginViewModel.getUser()
        val intent = Intent(this, MainActivity::class.java)
        intent.putExtra("userId", user?.userId)
        intent.putExtra("displayName", user?.displayName)
        intent.putExtra("myToken", user?.token)
        user?.urls?.get("getNettyConfig")?.apply {
            intent.putStringArrayListExtra(
                "nettyUrls",
                this as ArrayList<String>
            )
        }
        startActivity(intent)
        setResult(Activity.RESULT_OK)
        //Complete and destroy login activity once successful
        finish()
    }

    private fun showLoginFailed(@StringRes errorString: Int) {
        Toast.makeText(applicationContext, errorString, Toast.LENGTH_SHORT).show()
    }
}

/**
 * Extension function to simplify setting an afterTextChanged action to EditText components.
 */
fun EditText.afterTextChanged(afterTextChanged: (String) -> Unit) {
    this.addTextChangedListener(object : TextWatcher {
        override fun afterTextChanged(editable: Editable?) {
            afterTextChanged.invoke(editable.toString())
        }

        override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}

        override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
    })
}